<?php
require_once ("facebook.php");
require_once ("chinese.php");

class BookController extends Zend_Controller_Action {
	
	const CATEGORY = 'Books';
	const CACHE_INTERVAL = '10';
	private $currency;
	private $user;
	private $book;
	private $userBook;
	private $userBookCondition;
	private $searchDataCache;
	private $logger;
	private $mailQueue;
	
	public function init() {
		$this->currency = new Currency();
		$this->user = new User();
		$this->book = new Book();
		$this->userBook = new UserBook();
		$this->userBookCondition = new UserBookCondition();
		$this->searchDataCache = new SearchDataCache();
		$this->mailQueue = new MailQueue();
		$this->logger = Zend_Registry::get ( "logger" );
		
		$this->initView();
		$this->_flashMessenger = $this->_helper->getHelper('FlashMessenger');		 
		$this->view->flashmsgs = $this->_flashMessenger->getMessages();
	}
	
	/*
	 * render content later to improve the performance
	 * */
    public function renderajaxAction(){
    	
		$this->_helper->viewRenderer->setNoRender();   //view info disabled
		$this->_helper->getHelper('layout')->disableLayout(); //template disabled
		
    	$type= $this->getRequest()->getParam('type');
    	
    	$returnJson = null;
    	
    	if ($type=="fetchPrice"){
    		$amazonLink = $this->getRequest()->getParam('amazonLink');
    		$isbn = $this->getRequest()->getParam('isbn');
    	
		 	$content = $this->view->bookPriceDetail($isbn,$amazonLink);
    		$returnJson = array(
          		"content" => $content
        	);
    	}
        
        echo Zend_Json::encode($returnJson);
    }
    
	public function fetchajaxAction(){
		
		$this->_helper->viewRenderer->setNoRender();   //view info disabled
		$this->_helper->getHelper('layout')->disableLayout(); //template disabled
		
    	$keyword = $this->getRequest()->getParam('keyword');
    	$page = $this->getRequest()->getParam('page');
		
        $config = Zend_Registry::get('config');
        $amazonApiKey = $config->amazon->api->key;
        $amazonSecretKey = $config->amazon->secret->key;
            
        $cachedSearchData = $this->searchDataCache->findActiveByCategoryKeywordAndPage(self::CATEGORY, $keyword, $page);
        $hasNext = true;
        $hasPrev = false;
        $nextPage = 1;
        $prevPage = 1;
        // check if the search result is already cached, 
        // if so, read it from local db
        // otherwise, request from amazon service
        if (isset($cachedSearchData)) {
            $results = unserialize($cachedSearchData->data);
            // here you can get if the current page has next page.
         	$hasNext = $cachedSearchData->has_next;
         	$nextPage = $cachedSearchData->page + 1;
         	if ($cachedSearchData->page > 1) {
         		$hasPrev = true;
         		$prevPage = $cachedSearchData->page - 1;
         	}
        } else {
        	$amazon = new Zend_Service_Amazon($amazonApiKey, 'US', $amazonSecretKey);
        	$results = $amazon->itemSearch(array(
            'SearchIndex'   => self::CATEGORY,
            'Keywords'      => $keyword,
            'ItemPage' => $page,
            'ResponseGroup' => 'Medium'));
        	
        	$db = Zend_Registry::get('db');
	        $db->beginTransaction();
	        $currentTime = $this->_helper->generator->generateCurrentTime();
	        
	        foreach($results as $result) {
	        	$data[$result->ISBN] = $result;
	        }
	        $hasNext = $this->checkHasNextPage($page, $results->totalResults());
	        $nextPage = $page + 1;
        	if ($page > 1) {
         		$hasPrev = true;
         		$prevPage = $page - 1;
         	}
	        
	        $this->searchDataCache->cacheSearchData(
	             self::CATEGORY, $keyword, $page, serialize($data),
	             $hasNext,
	             $currentTime,
	             $this->_helper->generator->manipulatDate($currentTime, self::CACHE_INTERVAL, Zend_Date::MINUTE)
	        );
	        $db->commit();
        }
        // convert amazon resultset into a normal array
        // to serialize it later
        foreach($results as $result) {
        	$dataInSession[$result->ASIN] = $this->parseAmazonItem($result);
        }
        
        SessionUtil::setProperty(Constant::KEY_SEARCH_RESULT, $dataInSession);
                   
        $list = $this->view->bookFetchList($dataInSession,"amazonList");
        
        $returnJson = array(
          "list" => $list,
          "hasNext" => $hasNext,
          "nextPage" => $nextPage,
          "hasPrev" => $hasPrev,
          "prevPage" => $prevPage
        );
        echo Zend_Json::encode($returnJson);
        
	}
	
	public function updatestatusajaxAction(){
				
		$this->_helper->viewRenderer->setNoRender();   //view info disabled
		$this->_helper->getHelper('layout')->disableLayout(); //template disabled
		
		$uid = $this->_helper->user->getUserData()->id;
		$user = $this->user->findById($uid);
		
    	$isbn = $this->getRequest()->getParam("bid");
		$book = $this->book->findByISBN($isbn);
		$status = $this->getRequest()->getParam("status");
		
		if ($status == "available"){
			$this->userBook->updateBookStatus($book,$user,UserBookStatus::AVAILABLE);	
		} else if ($status == "letout"){
			$this->userBook->updateBookStatus($book,$user,UserBookStatus::LETOUT);	
		} else if ($status == "sold"){
			$this->userBook->updateBookStatus($book,$user,UserBookStatus::SOLD);	
		}
		
		$userBook = $this->userBook->findByBookAndUser($book->id, $user->id);
		Activity::logActivity(Activity::USER_UPDATE_BOOK_STATUS, $user->id, $userBook->id, $this->_helper->generator->generateCurrentTime());
		
		echo $status;
	}
	
	private function checkHasNextPage($currentPage, $totalResults) {
		$ret = false;
		if (SearchDataCache::PAGE_SIZE * $currentPage < $totalResults) {
			$ret = true;
		}
		return $ret;
	}
	
	/**
	 * Add book action,
	 * 1. search book in amazon
	 * 2. add it to user's own list.
	 */
	public function fetchAction() {
		
		if ($this->_helper->user->isLoggedIn()) {
		//	$userData = $this->_helper->user->getUserData();
        //    $this->view->userData = $userData;
            $config = Zend_Registry::get('config');
         	$this->view->headScript ()->appendFile ( $config->baseurl . '/js/fetchAmazon.js' ); 
                    
            // action body
            $form = new SearchForm();
            $this->view->form = $form;
    		
            $this->view->pageTitle=  "Fetch and add a book from Amazon";           
            
		    $manualForm = new ManualAddBookFormISBNOnly();
            $this->view->manualForm = $manualForm;
            
			$config = Zend_Registry::get("config");
        	$amazonApiKey = $config->amazon->api->key;
        	$amazonSecretKey = $config->amazon->secret->key;
            		
            if ($this->getRequest ()->isPost ()) {
                if ($manualForm->isValid ( $_POST )) {
                	$source = $manualForm->getValue("source");
                	$isbn = $manualForm->getValue("ISBN");
                	$book = $this->book->findByISBN($isbn);
                	if (empty($book)) {
                		// try to fetch book's isbn from amazon
                		$amazon = new Zend_Service_Amazon($amazonApiKey, 'US', $amazonSecretKey);
			            $results = $amazon->itemSearch(array(
			            'SearchIndex'   => self::CATEGORY,
			            'Power' => 'isbn:'.$isbn,
			            'ResponseGroup' => 'Medium'));
			            
	                	$totalResults = $results->totalResults();
	                	
						if ($totalResults == 1) {
							foreach ($results as $result) {
								$book = $this->parseAmazonItem($result);
								
								$data = array(
								    "source" => BookSource::AMAZON,
			                        "ASIN" => $book->ASIN,
			                        "detail_page_url" => $book->detail_page_url,
			                        "name" => $book->name,
			                        "description" => $book->description,
			                        "ISBN" => $book->ISBN,
			                        "ISBN13" => $book->ISBN13,
			                        "small_image" => $book->small_image,
			                        "medium_image" => $book->medium_image,
			                        "large_image" => $book->large_image,
			                        "currency" => $book->currency,
			                        "amount" => $book->amount,
			                        "author" => $book->author,
			                        "binding" => $book->binding,
			                        "manufacturer" => $book->manufacturer,
			                        "number_of_pages" => $book->number_of_pages,
			                        "publication_date" => $book->publication_date,
			                        "publisher" => $book->publisher,
			//                      "release_date" => $book->release_date
									"status" => BookStatus::ACTIVE
			                    );
			                    
								$bookId = $this->book->addBook($data);
							}
							
							$this->_redirect($config->baseurl."/book/add/id/".$book->ISBN."/f/0");
						} else {
							$this->logger->log ( $isbn." is not found on Amazon or more than one matches.", Zend_Log::WARN );
						}
                		// go to manual add book form
                		$this->_redirect($config->baseurl."/book/manualadd2/isbn/".$isbn);
                	} else {
                		// book already exist, go to add page step2 directly
                		$this->_redirect($config->baseurl."/book/add/id/".$isbn."/f/0");
                	}
                }
            }
            
		} else {
			$this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
        }
	}
	
	/**
	 * Show book detail when add new book.
	 */
	public function addAction() {
		if ($this->_helper->user->isLoggedIn()) {
			$userData = $this->_helper->user->getUserData();
			$config = Zend_Registry::get('config');
	    	$amazonApiKey = $config->amazon->api->key;
	    	$amazonSecretKey = $config->amazon->secret->key;
	    	
			$isbn = $this->_getParam('id');
			$bookInDb = $this->book->findByISBN($isbn);
			
            $this->view->pageTitle=  "Describe your book condition";
			if (empty($bookInDb)) {
				$dataInSession = SessionUtil::getProperty(Constant::KEY_SEARCH_RESULT);
                if (isset($dataInSession) && is_array($dataInSession)) {
                	$book = $dataInSession["$isbn"];
                } else {
                	throw new Zend_Exception("Book is not found, ISBN: ".$isbn);
                }
			} else {
				$book = $bookInDb;
			}
			
			$form = new AddBook($book);
			$this->view->form = $form;
			$this->view->book = $book;
			if ($this->getRequest ()->isPost ()) {
				if ($form->isValid ( $_POST )) {
					$db = Zend_Registry::get("db");
					$db->beginTransaction();
					$data = array(
					    "source" => $form->getValue("source"),
						"ASIN" => $form->getValue("ASIN"),
						"detail_page_url" => $form->getValue("detail_page_url"),
						"name" => $form->getValue("name"),
						"description" => $form->getValue("description"),
						"ISBN" => $form->getValue("ISBN"),
						"ISBN13" => $form->getValue("ISBN13"),
						"small_image" => $form->getValue("small_image"),
						"medium_image" => $form->getValue("medium_image"),
						"large_image" => $form->getValue("large_image"),
						"currency" => $form->getValue("currency"),
						"amount" => $form->getValue("amount"),
						"author" => $form->getValue("author"),
						"binding" => $form->getValue("binding"),
						"manufacturer" => $form->getValue("manufacturer"),
						"number_of_pages" => $form->getValue("number_of_pages"),
						"publication_date" => $form->getValue("publication_date"),
						"publisher" => $form->getValue("publisher"),
//						"release_date" => $form->getValue("release_date")
						"status" => $form->getValue("source") == BookSource::AMAZON ? BookStatus::ACTIVE : BookStatus::PENDING
					);
					
					$userId = $userData->id;
				    $bookId = $this->book->addBook($data);
					$book = $this->book->findById($bookId);
				    $currentDate = $this->_helper->generator->generateCurrentTime();
					$userBookCondition = $this->generateUserBookCondition($form->getValue("condition"));
					$userBookUsage = $this->generateUserBookCondition($form->getValue("usage"));
					$note = trim($form->getValue("note"));
					$data = array(
						"book_id" => $bookId,
						"user_id" => $userId,
						"condition" => $userBookCondition,
						"usage" => $userBookUsage,
					    "note" => $note,
						"created" => $currentDate,
						"modified" => $currentDate,
					    "status" => UserBookStatus::AVAILABLE
					);
					$userBookToBeAdded = $this->userBook->findByBookAndUser($bookId, $userId);
					// only log activity if it's a new book
				    $userBookId = $this->userBook->addOrUpdateUserBook($data);    
				    if (empty($userBookToBeAdded) && $book->status == BookStatus::ACTIVE) {
                        Activity::logActivity(Activity::USER_ADD_BOOK, $userId, $userBookId, $this->_helper->generator->generateCurrentTime());                   		    
				    }
                    $db->commit();
                    
                    $loggedInFacebook = $this->_helper->user->isLoggedInFacebookUser();
                    if ($loggedInFacebook["loggedIn"] && $book->status == BookStatus::ACTIVE) {
	                    // OPTIONAL
	                    // post to facebook news feed
	                    $user = $this->user->findById($this->_helper->user->getUserData()->id);
	                    $this->postNewsFeedAction($this->book->findById($bookId),$user);                    
                    }
                    if ($book->status == BookStatus::PENDING) {
                    	$this->_flashMessenger->addMessage("Thanks for your contribution, the book is waiting for approval, we will get back to you VERY soon!");
                    } else if ($book->status == BookStatus::ACTIVE) {
                    	$this->_flashMessenger->addMessage("Your book is added successfully!");
                    }
					$this->_redirect("/book/detail/id/".$isbn);	
				}
			}
		} else {
			$this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
		}
	}

	/**
	 * Add book manually by providing ISBN,
	 * if ISBN is already exist, directly forward to next step,
	 * otherwise, add book detail in another form.
	 */
	/*
	public function manualaddAction() {
		$this->view->headScript ()->appendFile ( $config->baseurl . '/js/jquery.validate.min.js' );
//        $this->view->headScript ()->appendFile ( $config->baseurl . '/js/manualaddbook.js' );
        
		$config = Zend_Registry::get("config");
        $amazonApiKey = $config->amazon->api->key;
        $amazonSecretKey = $config->amazon->secret->key;
        
		if ($this->_helper->user->isLoggedIn()) {
            $userData = $this->_helper->user->getUserData();
            
            $form = new ManualAddBookFormISBNOnly();
            $this->view->form = $form;
            exit;
            if ($this->getRequest ()->isPost ()) {
                if ($form->isValid ( $_POST )) {
                	$source = $form->getValue("source");
                	$isbn = $form->getValue("ISBN");
                	$book = $this->book->findByISBN($isbn);
                	print_r($book);exit;
                	if (empty($book)) {
                		// try to fetch book's isbn from amazon
                		$amazon = new Zend_Service_Amazon($amazonApiKey, 'US', $amazonSecretKey);
			            $results = $amazon->itemSearch(array(
			            'SearchIndex'   => self::CATEGORY,
			            'Power' => 'isbn:'.$isbn,
			            'ResponseGroup' => 'Medium'));
			            
	                	$totalResults = $results->totalResults();
	                	exit;
						if ($totalResults == 1) {
							foreach ($results as $result) {
								$book = $this->parseAmazonItem($result);
								
								$data = array(
								    "source" => BookSource::AMAZON,
			                        "ASIN" => $book->ASIN,
			                        "detail_page_url" => $book->detail_page_url,
			                        "name" => $book->name,
			                        "description" => $book->description,
			                        "ISBN" => $book->ISBN,
			                        "ISBN13" => $book->ISBN13,
			                        "small_image" => $book->small_image,
			                        "medium_image" => $book->medium_image,
			                        "large_image" => $book->large_image,
			                        "currency" => $book->currency,
			                        "amount" => $book->amount,
			                        "author" => $book->author,
			                        "binding" => $book->binding,
			                        "manufacturer" => $book->manufacturer,
			                        "number_of_pages" => $book->number_of_pages,
			                        "publication_date" => $book->publication_date,
			                        "publisher" => $book->publisher,
			//                      "release_date" => $book->release_date
									"status" => BookStatus::ACTIVE
			                    );
			                    
								$bookId = $this->book->addBook($data);exit;
							}
							$this->_redirect($config->baseurl."/book/add/id/".$book->ISBN."/f/0");
						} else {
							$this->logger->log ( $isbn." is not found on Amazon or more than one matches.", Zend_Log::WARN );
						}
                		// go to manual add book form
                		$this->_redirect($config->baseurl."/book/manualadd2/isbn/".$isbn);
                	} else {
                		// book already exist, go to add page step2 directly
                		$this->_redirect($config->baseurl."/book/add/id/".$book->ISBN."/f/0");
                	}
                }
            }
		} else {
			$this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
		}
		
	}
	*/
	
	/**
	 * Manually add book step 2, add new book.
	 * Note: ISBN can be 10 or 13 characters, need to save to different columns in database
	 */
	public function manualadd2Action() {
	   if ($this->_helper->user->isLoggedIn()) {
            $isbn = $this->_getParam("isbn");
            $user = $this->_helper->user->getUserData();
            if (empty($isbn)) {
            	throw new Zend_Exception("ISBN is not given!");
            }
            $form = new ManualAddBookFormAddNew($isbn);
            $this->view->form = $form;
            
            if ($this->getRequest ()->isPost ()) {
                if ($form->isValid ( $_POST )) {
                	$isbn_temp = $form->getValue("ISBN");
                	if (strlen($isbn_temp) == 10) {
                		 $isbn = $isbn_temp;
                		 $isbn13 = $isbn_temp."_fake";
                	} else if (strlen($isbn_temp) == 13) {
                		$isbn = substr($isbn_temp, 0, 10)."_fake";
                		$isbn13 = $isbn_temp;
                	} else {
                		throw new Zend_Exception("ISBN must be either 10 or 13 characters");
                		$this->logger->log("ISBN: ".$isbn_temp." must be either 10 or 13 characters.", Zend_Log::ERR);
                	}
                    $name = $form->getValue("name");
                    
                    $data = array(
                        "source" => BookSource::MANUAL,
                        "ASIN" => $isbn,
                        "name" => $name,
                        "ISBN" => $isbn,
                    	"ISBN13" => $isbn13,
                        "currency" => 1,
                        "publication_date" => $this->_helper->generator->generateCurrentTime(),
                        "release_date" => $this->_helper->generator->generateCurrentTime(),
                        "status" => BookStatus::PENDING
                    );
                    
                    $db = Zend_Registry::get("db");
                    $db->beginTransaction();
                    $id = $this->book->addBook($data);
                    $book = $this->book->findById($id);
                    
//                    $data = array(
//						"book_id" => $d,
//						"user_id" => $user->id,
//						"condition" => $userBookCondition,
//						"usage" => $userBookUsage,
//					    "note" => $note,
//						"created" => $this->_helper->generator->generateCurrentTime(),
//						"modified" => $this->_helper->generator->generateCurrentTime(),
//					    "status" => UserBookStatus::AVAILABLE
//					);
//					$userBookToBeAdded = $this->userBook->findByBookAndUser($bookId, $userId);
//					$userBookId = $this->userBook->addOrUpdateUserBook($data);
					
                    $db->commit();
                    $this->_redirect($config->baseurl."/book/add/id/".$book->ISBN."/f/0");
                }
            }
        } else {
            $this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
        }
	}
	
	/**
	 * Fetch isbn from db using ajax.
	 */
	public function fetchisbnAction() {
		$this->_helper->viewRenderer->setNoRender();   //view info disabled
		$this->_helper->getHelper('layout')->disableLayout(); //template disabled
		
		$returnJson = array();
		$isbn = $this->_getParam("isbn");
		$book = $this->book->findByISBN($isbn);
		
		$returnJson["isbn"] = $isbn;
		if (isset($book)) {
			$returnJson["existBook"] = true;
			$returnJson["book"] = array(
			    "ISBN" => $book->ISBN,
			    "detailPageUrl" => $book->detail_page_url,
			    "name" => $book->name,
			    "description" => $book->description,
		        "smallImage" => $book->small_image,
			    "medium_image" => $book->medium_image,
			    "large_image" => $book->large_image
			);
		} else {
			$returnJson["existBook"] = false;
		}
		echo Zend_Json::encode($returnJson);
	}
	
	public function testAction() {
		$book = $this->book->findById(1);
		$this->postNewsFeedAction($book);
		exit;
	}
	
	/**
	 * Post book info to facebook news feed.
	 * 
	 */
	private function postNewsFeedAction($book, $user) {
		$userBook = new UserBook();
		$userBook = Book::getUserBook($book, $user);
		$conditions = UserBookCondition::getConditionStrings($userBook->condition);
		$usages = UserBookUsage::getUsageStrings($userBook->usage);
		
		$msg = 'I have this book ('.implode(" , ",$conditions).') for '.implode(" , ",$usages);
		if (!empty($userBook->note))
		$msg .=	' "'.$userBook->note.'"';
        
		$config = Zend_Registry::get("config");
		$fbUserInfo = $this->_helper->user->isLoggedInFacebookUser();
		if ($fbUserInfo["loggedIn"]) {
			$facebook = $fbUserInfo["facebook"];
			$attachment = array('message' => $msg,
			'name' => $book->name,
			'link' => $config->baseurl."book/detail/id/".$book->ISBN."?vl=".(empty($user->view_location) ? $user->location : $user->view_location),
			'description' => 'I have '.count(User::getBooks ( $user, UserBookStatus::AVAILABLE )).' books on this website, join to exchange?',
			'picture' => "http://".$book->small_image
			);
			$result = $facebook->api("/me/feed", "post", $attachment);
		}
	}
	
	/**
	 * Parse amazon item into Book object.
	 * 
	 * @param $amazonItem
	 * @return return Book object
	 */
	private function parseAmazonItem($amazonItem) {
		$book = new Book();
		$book->source = BookSource::AMAZON;
		$book->ASIN = $amazonItem->ASIN;
		$book->detail_page_url = $amazonItem->DetailPageURL;
		$book->name = $amazonItem->Title;
		if (!empty($amazonItem->EditorialReviews)) {
			$book->description = $amazonItem->EditorialReviews[0]->Content;
		} else {
			$book->description = null;
		}
		// if the ISBN is not found, which it should not
		// then use ASIN as ISBN + fake as ISBN
		if (!empty($amazonItem->ISBN)) {
			$book->ISBN = $amazonItem->ISBN;
		} else {
			$book->ISBN = $amazonItem->ASIN."_fake";
		}
		if (!empty($amazonItem->Feature)) {
			$book->ISBN13 = trim(substr($amazonItem->Feature[0], 7));
		} else {
			$book->ISBN13 = $amazonItem->ASIN."_fake";
		}
		if (!empty($amazonItem->SmallImage)) {
			$book->small_image = $amazonItem->SmallImage->Url->getHost().$amazonItem->SmallImage->Url->getPath();
		} else {
			$book->small_image = null;
		}
	   if (!empty($amazonItem->MediumImage)) {
            $book->medium_image = $amazonItem->MediumImage->Url->getHost().$amazonItem->MediumImage->Url->getPath();
        } else {
        	$book->medium_image = null;
        }
        if (!empty($amazonItem->LargeImage)) {
            $book->large_image = $amazonItem->LargeImage->Url->getHost().$amazonItem->LargeImage->Url->getPath();
        } else {
        	$book->medium_image = null;
        }
		if (!empty($amazonItem->CurrencyCode)) {
			$book->currency = $this->currency->findByCode($amazonItem->CurrencyCode)->id;
		} else {
			$book->currency = 1;
		}
		if (!empty($amazonItem->Amount)) {
			$book->amount = $amazonItem->Amount;
		} else {
			$book->amount = 0;
		}
		if (!empty($amazonItem->Author)) {
			$book->author = $this->generateAuthorString($amazonItem->Author);
		} else {
			$book->author = null;
		}
		$book->binding = $amazonItem->Binding;
		if (!empty($amazonItem->Manufacturer)) {
			$book->manufacturer = $amazonItem->Manufacturer;
		}
		
		if (!empty($amazonItem->NumberOfPages)) {
			$book->number_of_pages = $amazonItem->NumberOfPages;
		} else {
			$book->number_of_pages = 0;
		}
		if (!empty($amazonItem->PublicationDate)) {
			$book->publication_date = $amazonItem->PublicationDate;
		}
		if (!empty($amazonItem->Publisher)) {
			$book->publisher = $amazonItem->Publisher;
		}
//		$book->release_date = property_exists('Zend_Service_Amazon_Item ', 'ReleaseDate') ? null : $amazonItem->ReleaseDate;
		return $book;
	}
	
	/**
	 * Generate author string, concatenate author by comma.
	 * 
	 * @param $authors
	 * @return string return concatenated author string
	 */
	private function generateAuthorString($authors) {
		$authorString="";
		if (is_array($authors)) {
			foreach ($authors as $author) {
				$authorString .= ($author.",");
			}
		} else {
			$authorString = $authors;
		}
		return substr($authorString, strlen($authorString)-1) == "," ? substr($authorString, 0, strlen($authorString)-1) : $authorString;
	}
	
	/**
	 * Return user book condition concatenated string.
	 * 
	 * @param $conditionInArray conditions in array
	 */
	private function generateUserBookCondition($conditionInArray) {
		$concatenatedCondition="";
		if (is_array($conditionInArray)) {
			foreach ($conditionInArray as $condition) {
				$concatenatedCondition.=($condition.',');
			}
		}
		if (substr($concatenatedCondition, strlen($concatenatedCondition)-1) == ',') {
			$concatenatedCondition = substr($concatenatedCondition, 0, strlen($concatenatedCondition)-1);
		}
		return $concatenatedCondition;
	}
	
	
	/**
	 * Show list of books in search in site page.
	 */
	public function listAction() {
		
		
		$cityId = $this->_helper->user->getUserViewCity();
		
		$keywords = strtolower($this->_getParam("keywords"));
		$searchKeys = explode(' ', trim($keywords));
		
		$searchResult = array();
		$searchScope = "Book";
		
	    if (!is_array($searchKeys) || empty($searchKeys[0])) {
            $searchResult = $this->generateAllResult($cityId);
        } else {
        	$searchResult = $this->generateResult("Book", $searchKeys, $cityId);
        }
		$pageModel = new BookSearchResultPageModel();
		$pageModel->keywords = $keywords;
		$pageModel->searchResult = $searchResult;
        $this->view->pageModel = $pageModel;
        $this->view->keywords = $keywords;
        $this->view->searchResult = $searchResult;
            
        $this->view->paginator = $this->_helper->paginator( $this->_getParam ( 'page', 1 ), $searchResult );
                      
        $this->view->pageTitle=  "HeyIdleBooks : ".$keywords;
        $this->view->pageDesc=  "HeyIdleBooks : ".$keywords;
	}
	
	/**
	 * Show book detail, it shows book details and users who have the book.
	 */
	public function detailAction() {
		$config = Zend_Registry::get ( 'config' );
		$this->view->headScript ()->appendFile ( $config->baseurl . '/js/bookDetail.js' );
		
		$viewLocationId = $this->_getParam("vl");
		if (!empty($viewLocationId)) {
			SessionUtil::setProperty(Constant::KEY_CITY_ID, $viewLocationId);
		}
		
		$user = null;
		if ($this->_helper->user->isLoggedIn()) {
			$user = $this->user->findById($this->_helper->user->getUserData()->id);
			
			// Update user view location to latest
			if (!empty($viewLocationId)) {
				$data = array(
				    User::VIEW_LOCATION => $viewLocationId
				);
				$this->user->updateUserSettings($user->id, $data);
			}
		}
		$isbn = $this->_getParam("id");
		if (empty($isbn)) {
			throw new Zend_Exception("ISBN is missing!");
		}
		$book = $this->book->findByISBN($isbn);
		if (empty($book)) {
			throw new Zend_Exception("Book is not found!");
		}
		
		$pageModel = new BookDetailPageModel();
		$pageModel->setUser($user);
		$pageModel->setBook($book);
		
		// get user city,
		// if user login, then get user's top city
		// otherwise, get city from session.
		$userCity = $this->view->userCity();
		$pageModel->usersHasBook = Book::getUser($book, null, $userCity);
		
		$this->view->pageModel = $pageModel;
        $this->view->pageTitle=  $book->name;
        if(isset($book->author)) {
        	$this->view->pageTitle .= " : ".$book->author;
        }
        	
        $this->view->pageDesc = $this->view->pageTitle;
	}
	
	/**
	 * Get all books by given city, wrap into a search result.
	 * 
	 * @param $cityId
	 * @return return search result
	 */
	private function generateAllResult($cityId) {
		$result = array();
		$totalBooks = Book::getTotalBooks($cityId, null);
		$index = 0;
		foreach ($totalBooks as $bookObj) {
			$book = $this->book->findById($bookObj->bid);
			$array = array();
			$array[Custom_Search_Lucene_Document::NAME] = $book->name;
			$array[Custom_Search_Lucene_Document::DESCRIPTION] = $book->description;
			$array[Custom_Search_Lucene_Document::AUTHOR] = $book->author;
			$array[Custom_Search_Lucene_Document::ISBN] = $book->ISBN;
			$array[Custom_Search_Lucene_Document::PUBLICATION_DATE] = $book->publication_date;
			$array[Custom_Search_Lucene_Document::BINDING] = $book->binding;
			$array[Custom_Search_Lucene_Document::ASIN] = $book->ASIN;
			$array[Custom_Search_Lucene_Document::SMALL_IMAGE] = $book->small_image;
			$array[Custom_Search_Lucene_Document::KEY] = $book->id;
			$result[$index++] = $array;
		}
		return $result;
	}
	
    /**
     * Generate result according to search scope.
     * 
     * @param $searchScope
     * @param $searchKeys
     * @param $cityId
     * @return return array which contains result
     */
    private function generateResult($searchScope, $searchKeys, $cityId) {
        $result = array();
        
        // Search different scope, search friend or invitation
        if ($searchScope == "Book") {
            $class = 'Book';
            SearchIndexer::setIndexDirctory('book');
        }
        
//        Zend_Search_Lucene_Analysis_Analyzer::setDefault(new CN_Lucene_Analyzer());
		Zend_Search_Lucene_Analysis_Analyzer::setDefault(new CN_Lucene_Analyzer());
        try {
            $index = Zend_Search_Lucene::open(SearchIndexer::getIndexDirectory());
        } catch (Zend_Search_Lucene_Exception $e) {
            $this->_redirect('error/');
        }
        Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('UTF-8');
        /*
        if (count($searchKeys) > 1) {
            $multiq = new Zend_Search_Lucene_Search_Query_MultiTerm();
            foreach ($searchKeys as $searchKey) {
              $term1 = new Zend_Search_Lucene_Index_Term($searchKey);
              $multiq->addTerm($term1);
            }
            $queryHits = $index->find($multiq);
        } else {
            $pattern = new Zend_Search_Lucene_Index_Term($searchKeys[0].'*');
            $userQuery = new Zend_Search_Lucene_Search_Query_Wildcard($pattern);
            $queryHits = $index->find($userQuery);
        }
        */
        $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($searchKeys[0]); 
        $queryHits = $index->find($userQuery);
        switch ($searchScope) {
            case "Book":
                $index = 0;
                foreach ($queryHits as $hit) {
                	if ($this->inCity($hit->cities, $cityId)) {
                		$array[Custom_Search_Lucene_Document::NAME] = $hit->name;
	                    $array[Custom_Search_Lucene_Document::DESCRIPTION] = $hit->description;
	                    $array[Custom_Search_Lucene_Document::AUTHOR] = $hit->author;
	                    $array[Custom_Search_Lucene_Document::ISBN] = $hit->ISBN;
	                    $array[Custom_Search_Lucene_Document::PUBLICATION_DATE] = $hit->publication_date;
	                    $array[Custom_Search_Lucene_Document::BINDING] = $hit->binding;
	                    $array[Custom_Search_Lucene_Document::ASIN] = $hit->ASIN;
	                    $array[Custom_Search_Lucene_Document::SMALL_IMAGE] = $hit->small_image;
	                    $array[Custom_Search_Lucene_Document::KEY] = $hit->key;
	                    $result[$index++] = $array;
                	}
                }
                break;
        }
        return $result;
    }
    
    /**
     * Check if given city is in the book city string
     *  
     * @param $bookCity book city string
     * @param $cityId city id
     * @param return true if city id is in book city string
     */
    private function inCity($bookCity, $cityId) {
    	$ret = false;
    	$cities = explode(",", $bookCity);
    	foreach ($cities as $city) {
    		if ($city == $cityId) {
    			$ret = true;
    			break;
    		}
    	}
    	return $ret;
    }
    
    /**
     * Edit book action.
     */
    public function editAction() {
    	if ($this->_helper->user->isLoggedIn()) {
    		$uid = $this->_helper->user->getUserData()->id;
    		$user = $this->user->findById($uid);
    		$isbn = $this->_getParam("id");
    		$book = $this->book->findByISBN($isbn);
    		$userBook = Book::getUserBook($book, $user);
    		$editBookForm = new EditBook($userBook, $book);
    		$this->view->form = $editBookForm;
    		$this->view->book = $book;
    		
            $this->view->pageTitle=  "Update book condition for ".$book->name;
    		
    		if ($this->getRequest ()->isPost ()) {
                if ($editBookForm->isValid ( $_POST )) {
                	$db = Zend_Registry::get("db");
                	$db->beginTransaction();
                	$userId = $user->id;
                    $currentDate = $this->_helper->generator->generateCurrentTime();
                    $userBookCondition = $this->generateUserBookCondition($editBookForm->getValue("condition"));
                    $userBookUsage = $this->generateUserBookCondition($editBookForm->getValue("usage"));
                    $note = trim($editBookForm->getValue("note"));
                    $status = $editBookForm->getValue("status");
                    $data = array(
                        "book_id" => $book->id,
                        "user_id" => $userId,
                        "condition" => $userBookCondition,
                        "usage" => $userBookUsage,
                        "note" => $note,
                        "created" => $currentDate,
                        "modified" => $currentDate
                        //,"status" => $status
                    );
                    $this->userBook->addOrUpdateUserBook($data);
                    $db->commit();
	            	$this->_flashMessenger->addMessage("Your book information is updated!");
                    $this->_redirect("/book/detail/id/".$isbn);
                }
    		}
    	} else {
    		$this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
    	}
    }
    
    /**
     * Approve book action.
     */
    public function approveAction() {
    	if ($this->_helper->user->isLoggedIn()) {
    		$user = $this->_helper->user->getUserData();
    		if (User::hasAccessRight($user, AccessRight::ADMIN)) {
	    		$isbn = $this->_getParam("id");
	    		$book = $this->book->findByISBN($isbn);
	    		
	    		$db = Zend_Registry::get("db");
	    		$db->beginTransaction();
	    		$users = Book::getUser($book, UserBookStatus::AVAILABLE, null);
	    		foreach ($users as $user) {
	    			$userBook = Book::getUserBook($book, $user);
	    			if ($book->status != BookStatus::ACTIVE) {
		    			Activity::logActivity(Activity::USER_ADD_BOOK, $user->id, $userBook->id, $this->_helper->generator->generateCurrentTime());
		    			$this->book->updateStatus($book->id, BookStatus::ACTIVE);
		    			
		    			// log activity
		            	Activity::logActivity(
		            	  Activity::APPROVED_BOOK_REQUEST, 
		            	  $user->id,
		            	  $userBook->id,
		            	  $this->_helper->generator->generateCurrentTime()
		            	);
		    			// notification email
		    			$extra = array(
		    				"book" => $book
		    			);
		    			$emailMessage = EmailTemplate::getEmailMessage(Activity::APPROVED_BOOK_REQUEST, null, $user, $extra);
		    			$this->mailQueue->addToQueue(
		            	  Activity::APPROVED_BOOK_REQUEST, 
		            	  EmailTemplate::SUBJECT_APPROVED_BOOK_REQUEST, 
	//	            	  $senderUser->email,
	                      Constant::SYS_NO_REPLY_EMAIL,  
		            	  $user->email, 
		            	  $emailMessage, 
		            	  $this->_helper->generator->generateCurrentTime());
		            			
	    			}
	    		}
	    		$db->commit();
	    		$this->_redirect("/admin/viewpendingbooks");
    		} else {
    			throw new Exception("User don't have permission to access admin");
    		}
    	} else {
    		$this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
    	}
    }
    
    /**
     * Complete book information, used by Admin
     */
    public function completeinfoAction() {
    	if ($this->_helper->user->isLoggedIn()) {
    		$user = $this->_helper->user->getUserData();
    		if (User::hasAccessRight($user, AccessRight::ADMIN)) {
	            $isbn = $this->_getParam("id");
	            $book = $this->book->findByISBN($isbn);
	            
	            $form = new CompleteBookInfo($book);
	            $this->view->form = $form;
	            if ($this->getRequest ()->isPost ()) {
	                if ($form->isValid ( $_POST )) {
	                	$bookId = $form->getValue("id");
	                	$data = array(
	//                		Book::ID => $bookId,
							Book::SOURCE => $form->getValue(Book::SOURCE),
							Book::DETAIL_PAGE_URL => $form->getValue(Book::DETAIL_PAGE_URL),
	                		Book::NAME => $form->getValue(Book::NAME),
	                		Book::DESCRIPTION => $form->getValue(Book::DESCRIPTION),
	                		Book::ISBN => $form->getValue(Book::ISBN),
	                		Book::ISBN13 => $form->getValue(Book::ISBN13),
	                		Book::AUTHOR => $form->getValue(Book::AUTHOR),
	                		Book::SMALL_IMAGE => $form->getValue(Book::SMALL_IMAGE),
	                		Book::MEDIUM_IMAGE => $form->getValue(Book::MEDIUM_IMAGE),
	                		Book::LARGE_IMAGE => $form->getValue(Book::LARGE_IMAGE),
	                		Book::AMOUNT => $form->getValue(Book::AMOUNT),
	                		Book::CURRENCY => $form->getValue(Book::CURRENCY),
	                		Book::PUBLICATION_DATE => $form->getValue(Book::PUBLICATION_DATE),
	                		Book::PUBLISHER => $form->getValue(Book::PUBLISHER),
	                		Book::MANUFACTURER => $form->getValue(Book::MANUFACTURER)
	                	);
	                	$this->book->updateBook($data, $book->id);
	                }
	            }
    		} else {
    			throw new Exception("User don't have permission to access admin");
    		}
        } else {
        	$this->_redirect( "/user/login?next=".urlencode($this->_helper->generator->getCurrentURI()) );
        }
    }
}
?>